﻿using System.Runtime.Serialization;
using System.Xml.Linq;
using NCMIS.Produce;

namespace NCMIS.ObjectModel.MetaData
{
    /// <summary>
    /// Represents the type definition base type, that describes an object types attribute values and property defintions.
    /// </summary>
    [KnownType(typeof(TypePolicyDefinition))]
    [KnownType(typeof(TypeRelationshipDefinition))]
    [KnownType(typeof(TypeFolderDefinition))]
    [KnownType(typeof(TypeDocumentDefinition))]
    [DataContract(Name = "type", Namespace = CmisNs.Cmis)]
    public class TypeDefinition
    {
        [IgnoreDataMember]
        public PropertyDefinition[] PropertyDefinitions
        {
            get;
            set;
        }

        [DataMember(Name = "id", Order = 1)]
        public string Id
        {
            get;
            set;
        }

        [DataMember(Name = "localName", Order = 2)]
        public string LocalName
        {
            get;
            set;
        }

        [DataMember(Name = "localNamespace", Order = 3)]
        public string LocalNamespace
        {
            get;
            set;
        }

        [DataMember(Name = "displayName", Order = 4)]
        public string DisplayName
        {
            get;
            set;
        }

        [DataMember(Name = "queryName", Order = 5)]
        public string QueryName
        {
            get;
            set;
        }

        [DataMember(Name = "description", Order = 6)]
        public string Description
        {
            get;
            set;
        }

        [DataMember(Name = "baseId", Order = 7)]
        public BaseObjectTypeId BaseId
        {
            get;
            set;
        }

        [DataMember(Name = "parentId", Order = 8)]
        public string ParentId
        {
            get;
            set;
        }

        [DataMember(Name = "creatable", Order = 9)]
        public bool Creatable
        {
            get;
            set;
        }

        [DataMember(Name = "fileable", Order = 10)]
        public bool Fileable
        {
            get;
            set;
        }

        [DataMember(Name = "queryable", Order = 11)]
        public bool Queryable
        {
            get;
            set;
        }

        [DataMember(Name = "fulltextIndexed", Order = 12)]
        public bool FulltextIndexed
        {
            get;
            set;
        }

        [DataMember(Name = "includedInSupertypeQuery", Order = 13)]
        public bool IncludedInSupertypeQuery
        {
            get;
            set;
        }

        [DataMember(Name = "controllablePolicy", Order = 14)]
        public bool ControllablePolicy
        {
            get;
            set;
        }

        [DataMember(Name = "controllableACL", Order = 15)]
        public bool ControllableAcl
        {
            get;
            set;
        }

        /// <summary>
        /// Returns a <see cref="System.Xml.Linq.XElement"/> RestAtom representation of this instance.
        /// </summary>
        /// <returns>A <see cref="System.Xml.Linq.XElement"/> object representation.</returns>
        public virtual XElement ToXElement()
        {
            XNamespace ns = CmisNs.Cmis;
            XNamespace nsra = CmisNs.Cmisra;

            XElement typeElement = new XElement(nsra + "type", new XAttribute(nsra + "id", this.Id),
                new XElement(ns + "id", this.Id),
                new XElement(ns + "localName", this.LocalName),
                new XElement(ns + "localNamespace", this.LocalNamespace),
                new XElement(ns + "displayName", this.DisplayName),
                new XElement(ns + "queryName", this.QueryName),
                new XElement(ns + "description", this.Description),
                new XElement(ns + "baseId", BaseIdToString(this.BaseId)),
                new XElement(ns + "creatable", this.Creatable),
                new XElement(ns + "fileable", this.Fileable),
                new XElement(ns + "queryable", this.Queryable),
                new XElement(ns + "fullTextIndexed", this.FulltextIndexed),
                new XElement(ns + "includedInSupertypeQuery", this.IncludedInSupertypeQuery),
                new XElement(ns + "controllablePolicy", this.ControllablePolicy),
                new XElement(ns + "controllableACL", this.ControllableAcl));
            foreach (PropertyDefinition propertyDefinition in this.PropertyDefinitions)
            {
                typeElement.Add(propertyDefinition.ToXElement());
            }

            return typeElement;
        }

        /// <summary>
        /// Converts a <see cref="NCMIS.Produce.BaseObjectTypeId"/> instance to a <see cref="System.String"/>. Preferably used when the DataContractSerializer is not used during serialization.
        /// </summary>
        /// <param name="baseObjectTypeId">The <see cref="NCMIS.Produce.BaseObjectTypeId"/> to convert to string.</param>
        /// <returns>A <see cref="System.String"/> instance.</returns>
        protected string BaseIdToString(BaseObjectTypeId baseObjectTypeId)
        {
            string baseIdString = string.Empty;
            switch (baseObjectTypeId)
            {
                case BaseObjectTypeId.CmisDocument:
                    baseIdString = "cmis:document";
                    break;
                case BaseObjectTypeId.CmisFolder:
                    baseIdString = "cmis:folder";
                    break;
                case BaseObjectTypeId.CmisPolicy:
                    baseIdString = "cmis:policy";
                    break;
                case BaseObjectTypeId.CmisRelationship:
                    baseIdString = "cmis:relationship";
                    break;
            }
            return baseIdString;
        }
    }
}
